#pragma region Description
/*
     Copyright © 2011 Jesse 'LorgonJortle' Wilkerson
     See licensing in source (.cpp) file, or at:
     <http://www.gnu.org/licenses/> (GPL)

     File: Game.h
     Author: Jesse 'LorgonJortle' Wilkerson
     Description:
          The Game class is essentially what runs LOGL::GLib. Every game created
          using LOGL::GLib inherits from Game, and gains its functionality. Game
          holds the Update and Draw methods that will power
          the final game. Game holds a dynamic vector of GameComponents
          that are automagically Updated and Drawn by the Game. Not all
          components need to be added to the Game, but for full automation, the
          feature is supported.
*/
#pragma endregion

#ifndef GAME_H
#define GAME_H

#define WIN32_LEAN_AND_MEAN

/*****************************************
                              OpenGL
*****************************************/
     #ifdef __APPLE__
         #include <OpenGL/OpenGL.h>
         #include <glew.h>
         #include <SDL/SDL.h>
         #include <SDL_ttf.h>
     #else
         #include <GL/glew.h>
         #include <SDL.h>
         #include <SDL_ttf.h>
     #endif
/****************************************/

/*****************************************
                         Standard C++
*****************************************/
     #include <bitset>
     #include <vector>
/****************************************/

/*****************************************
                         LOGL::GLib
*****************************************/
     /*****************************************
                                   Common
     *****************************************/
          #include "Vector2.h"
          #include "Vector3.h"
          #include "Vertex3.h"
          #include "Matrix.h"
          #include "GameComponent.h"
          #include "GameObject.h"
          #include "Font.h"
          #include "SpriteBatch.h"
          #include "ShaderManager.h"
          #include "Shaders.h"
          #include "Cube.h"
     /*****************************************
                                   Input
     *****************************************/
          #include "Keyboard.h"
          #include "Mouse.h"
     /*****************************************
                                   Content
     *****************************************/
          #include "Texture2.h"
          #include "Material.h"
          #include "MaterialGroup.h"
          #include "StaticModel.h"
     /*****************************************
                                   Math
     *****************************************/
          #include "Math.h"
     /*****************************************
                                   Utilities
     *****************************************/
          #include "Exception.h"
          #include "FrequencyCounter.h"
/****************************************/

using namespace LOGL_GLib::Common;
using namespace LOGL_GLib::Input;
using namespace LOGL_GLib::Content;
using namespace LOGL_GLib::Math;
using namespace LOGL_GLib::Utilities;

namespace LOGL_GLib
{
     class Game
     {
     public:
          /* Constructs the Game object. */
          Game();
          /* Destructs the Game object and free any indebted resources. */
          ~Game();

          /* Runs the game loop and automates the game. */
          GLvoid Run();

          /* Gets the last error to occur in the program. */
          std::string GetLastError() const;

          /* The exit code produced by the game. If it's not 0, it's an error. */
          GLint ExitCode;

     protected:
          /* Gets the current FPS of the game. */
          GLuint CurrentFPS();
          /* Gets the ideal FPS of the game. */
          GLuint IdealFPS();
          /* Sets the ideal FPS of the game. */
          GLvoid IdealFPS(GLuint _IdealFPS);
          /* Gets the millisecond step between frames. */
          GLuint FPSStep();
          /* Gets the current UPS of the game. */
          GLuint CurrentUPS();
          /* Gets the ideal UPS of the game. */
          GLuint IdealUPS();
          /* Sets the ideal UPS of the game. */
          GLvoid IdealUPS(GLuint _IdealUPS);
          /* Toggles fullscreen mode. */
          GLboolean ToggleFullscreen();
          /* Resizes the game window to the specified dimensions. */
          GLvoid ResizeWindow(GLint _Width, GLint _Height);
          /* Gets a pointer to the game's screen. */
          SDL_Surface* Screen() const;
          /* Gets the screen's width. */
          GLint ScreenWidth() const;
          /* Gets the screen's height. */
          GLint ScreenHeight() const;

          /* Initializes essential variables and prepares for content loading and the game loop. */
          virtual GLvoid Initialize();
          /* Loads any content that will be used for the game. */
          virtual GLvoid LoadContent();
          /* Updates under-the-hood game logic and any components. */
          virtual GLvoid Update();
          /* Handles low-level drawing and renders any components in the component list. */
          virtual GLvoid Draw();
          /* Releases any indebted content resources and prepares for Cleanup. */
          virtual GLvoid UnloadContent();
          /* Releases any indebted resources and cleans up before closing. */
          virtual GLvoid Cleanup();

          /* Pushes a quit event to SDL. */
          GLvoid Exit();

          /* The automated components handled by the Game. */
          std::vector<GameComponent> Components;
          /* Handles the loading and binding of GLSL shaders. */
          ShaderManager Shaders;
          /* Handles rendering of texture and images. */
          SpriteBatch Batch;

     private:
          /* Gets OpenGL up and running. */
          GLvoid InitializeGL();
          /* Keeps the game drawing at the ideal FPS. */
          GLboolean LimitFPS();
          /* Keeps the game updating at the ideal UPS. */
          GLboolean LimitUPS();

          /* The surface that represents our screen. */
          SDL_Surface* screen;

          /* Calculates the speed at which frames are rendered. */
          FrequencyCounter frameSpeed;
          /* Calculates the speed at which update cycles execute. */
          FrequencyCounter updateSpeed;
          /* The ideal FPS to run the game at. */
          GLuint idealFPS;
          /* The ideal UPS to run the game at. */
          GLuint idealUPS;
          /* Whether or not the game is in fullscreen mode. */
          GLboolean isFullscreen;
          /* The width of the game window. */
          GLint windowWidth;
          /* The height of the game window. */
          GLint windowHeight;

          /* The last error to occur in the program. */
          std::string lastError;

     }; /* Class Game. */
} /* Namespace LOGL_GLib. */

#endif
